home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
c
/
tick.zip
/
TICK.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-03-08
|
6KB
|
221 lines
/* tick.c - installs a function which is called every clock tick */
/* (c) - Amit Joshi, Princeton University
This code may be used freely for any noncommercial use. It may NOT
be used in any commercial package without written permission from
the author. This clause is to protect me from legal hassles with
the university about code developed here. This code is supplied
"AS IS" i.e. with no warranty. Do not remove this notice. Any
modifications should be clearly noted before redistribution.
**/
/** Amit Joshi
MAE Dept., Engg. Quad.
Princeton University
December 1987
**/
/**
The __tick__() and dosbusy() functions have been stolen from the
"rdir.c" code by Dean D. McCrory. The __tick__() has been
rewritten (and renamed from timer_handler()) to be more general.
Amit Joshi
January 1988
**/
#include <stdlib.h>
#include <stdio.h>
#include "tick.h"
/* Stuff for to handle the ctrl break functions */
static int __nc_brks = 0;
static char __abort = 1;
static void (* __c_brks[NCBRKS])();
/* Stuff to run timers */
static void interrupt (* __otimer)() = NULLIVFP;
static int __ntimers = 0;
static void (* __timers[NTIMERS])();
static char far * dosbusy_fl; /* dos maintains this */
/* The functions used in this file */
static int __cbrk(void);
static void __clean_timer(void);
static void interrupt __tick__(void);
static char far * getdosbusy(void);
static int
__cbrk(void) {
int nf;
if (!abort) {
for (nf = 0; nf < __nc_brks; ++nf)
(* __c_brks[nf])();
exit(1);
} else return 1;
}
static void
__clean_timer(void) {
if (__otimer == NULLIVFP) return; /* nothing set yet */
setvect(TIMER_INT,__otimer);
}
/* __tick__ ()
*
* This function intercepts the hardware timer interrupt. It checks the
* dosbusy flag and runs through a list of timer driven functions if safe
* to do so.
*/
static void interrupt
__tick__(void)
{
static int in_fl = 0;
int timer;
/* if the following statement is NOT coded, the 8259 blocks all hardware
interrupts including the keyboard interrupt. Since we wait for a key
in list_directory (), this causes the PC to lock up. This one took
a while to figure out */
outportb (0x20, 0x20); /* send eoi to 8259 */
(*__otimer) (); /* chain to previous timer handler */
if (! in_fl)
{
in_fl = 1; /* we are in our ISR */
if (! *dosbusy_fl )
/* run through the list of timers */
for (timer = 0; timer < __ntimers; ++timer)
if (__timers[timer] != NULLVFP)
(* __timers[timer])();
in_fl = 0;
}
return; /* return from ISR */
}
/* getdosbusy ()
*
* Gets the Dos busy flag through interrupt 34h. This Dos function returnes
* the busy flag address in es:bx. This is an UNDOCUMENTED feature of Dos,
* however it has worked in Dos versions 2.11 - 3.30 for me - Dean McCrory.
*/
static char far *
getdosbusy (void)
{
struct SREGS sregs; /* segment registers */
union REGS regs; /* normal registers */
regs.h.ah = 0x34; /* get dos busy flag address (UNDOCUMENTED) */
intdosx (®s, ®s, &sregs);
return (MK_FP (sregs.es, regs.x.bx));
}
int
install_timer(void (*func)(void))
{
int i = 0;
void __clean_timer();
void interrupt __tick__();
/* check if the function is already installed */
if (!__ntimers) {
__otimer = getvect(TIMER_INT);
/* Get address of DOS busy flag. */
dosbusy_fl = getdosbusy();
if (atexit(__clean_timer)) return 2;
install_cbrk(NULLVFP);
setvect(TIMER_INT,__tick__);
}
/* are we already installed ? */
for (i=0; i < __ntimers; i++)
if (__timers[i] == func) return 0;
/* enough space for another function ? */
if (__ntimers >= NTIMERS) return 1;
__timers[__ntimers++] = func;
return 0;
}
int
remove_timer(void (*func)(void))
{
int i = 0;
if (func == NULLVFP) {
__clean_timer();
__ntimers = 0;
return 0;
}
if (!__ntimers) return 1; /* No timers return func not there */
do {
/* have we found the function ? */
if (__timers[i] == func) {
/* is it the last one in the chain ? */
if (i++ == __ntimers) {
__timers[i-1] = NULLVFP;
} else {
/* move the chain backwards */
do {
__timers[i-1] = __timers[i]; i++;
} while(i <= __ntimers);
}
__ntimers--;
return 0;
} else i++;
} while (i < __ntimers);
return 1;
}
int
install_cbrk (void (* func)(void))
{
int i = 0;
if (!__nc_brks) {
setcbrk(1); /* ensure that ctrl break is enabled */
ctrlbrk(__cbrk);
__abort = 1;
}
if (func == NULLVFP) __abort = 1;
for (i = 0; i < __nc_brks; i++)
if (__c_brks[i] == func) return 0;
/* enough space for another function ? */
if (__nc_brks >= NCBRKS) return 1;
__c_brks[__nc_brks++] = func;
return 0;
}
int
remove_cbrk (void (* func)(void))
{
int i = 0;
if (func == NULLVFP) __abort = 0;
if (!__nc_brks) return 1; /* No timers return func not there */
do {
/* have we found the function ? */
if (__c_brks[i] == func) {
/* is it the last one in the chain ? */
if (i++ == __nc_brks) {
__c_brks[i-1] = NULLVFP;
} else {
/* move the chain backwards */
do {
__c_brks[i-1] = __c_brks[i]; i++;
} while(i <= __nc_brks);
}
__nc_brks--;
return 0;
} else i++;
} while (i < __nc_brks);
return 1;